package manager;

import java.io.Serializable;
import java.util.List;

import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;

import services.book.BookService;
import services.book.ReservationService;
import services.user.LoanService;
import systemconfig.SystemConfiguration;
import users.Person;
import util.Holiday;
import books.Book;
import books.BookReservation;
import books.Manager;
import exceptions.LoanLimitExceededException;

/**
 */
public class ReservationManager implements Serializable {

    private static final long serialVersionUID = 1L;

    @Autowired
    private ReservationService reservationService;

    @Autowired
    private LoanService loanService;

    @Autowired
    private BookService bookService;

    public BookService getBookService() {
        return bookService;
    }

    public void setBookService(final BookService bookService) {
        this.bookService = bookService;
    }

    private Manager manager;

    public void setManager(final Manager manager) {
        this.manager = manager;
    }

    public Manager getManager() {
        return manager;
    }

    public void setReservationService(final ReservationService reservationService) {
        this.reservationService = reservationService;
    }

    public ReservationService getReservationService() {
        return reservationService;
    }

    public void newCopyAvailable(final Book aCopy) {
        List<Person> persons = getReservationService().getNotificationList(aCopy.getInfo());
        getManager().sendCopyAvailableMailTo(persons);
    }

    public void cancelReservation(final BookReservation aReservation) {
        getReservationService().clearReservation(aReservation.getBook());
        if (aReservation.isSatisfied()) {
            Book copy = aReservation.getReservedCopy();
            getBookService().returnCopy(copy);
        }

    }

    public void cancelExpiredReservations() {
        List<BookReservation> expiredReservations = getReservationService().getSatisfiedReservations();

        for (BookReservation reservation : expiredReservations) {
            if (reservationOutOfDate(reservation)) {
                cancelReservation(reservation);
            }
        }
    }

    public boolean reservationOutOfDate(final BookReservation bookReservation) {
        DateTime copyReturned, expiresOn;
        copyReturned = bookReservation.getCopyReturnedDate();

        int daysOfReserve = SystemConfiguration.getInstance().getDaysCopyReserved();
        expiresOn = new Holiday(null, null).getNonHolidayDateFrom(copyReturned, daysOfReserve, SystemConfiguration
                .getInstance().getHolidayList());
        expiresOn = expiresOn.plusDays(1);

        return expiresOn.isBeforeNow();

    }

    public void validateReservationOrLoanFor(final Person aPerson) {

        int currentLoans = getReservationService().getReservationsOf(aPerson).size();
        int currentReservations = getLoanService().getCurrentLoansOf(aPerson).size();

        int limit = SystemConfiguration.getInstance().getMaxLoansPerUser();
        if (currentLoans + currentReservations >= limit) {
            throw new LoanLimitExceededException();
        }

    }

    public void setLoanService(final LoanService loanService) {
        this.loanService = loanService;
    }

    public LoanService getLoanService() {
        return loanService;
    }
}
